package com.appspot.entourage.ui.client;

import java.util.List;

import com.appspot.entourage.ui.shared.FieldVerifier;
import com.appspot.entourage.ui.shared.PersonResult;
import com.appspot.entourage.ui.shared.ProcessResult;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.TreeItem;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.VerticalSplitPanel;
import com.google.gwt.user.client.ui.HorizontalSplitPanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class EntourageGwt implements EntryPoint {
	/**
	 * The message displayed to the user when the server cannot be reached or
	 * returns an error.
	 */
	private static final String SERVER_ERROR = "An error occurred while "
			+ "attempting to contact the server. Please check your network "
			+ "connection and try again.";

	/**
	 * Create a remote service proxy to talk to the server-side Entourage service.
	 */
	private final EntourageServiceAsync entourageService = GWT
			.create(EntourageService.class);

	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		final Label errorLabel = new Label();

		// Add the nameField and sendButton to the RootPanel
		// Use RootPanel.get() to get the entire body element
		
		
		RootPanel root = RootPanel.get("appContainer");
		
		VerticalPanel verticalPanel = new VerticalPanel();
		root.add(verticalPanel);
		
		HorizontalPanel horizontalPanel = new HorizontalPanel();
		verticalPanel.add(horizontalPanel);
		
		Label lblRadius = new Label("Radius");
		horizontalPanel.add(lblRadius);
		
		final TextBox radiusField = new TextBox();
		horizontalPanel.add(radiusField);
		
		HorizontalSplitPanel horizontalSplitPanel = new HorizontalSplitPanel();
		verticalPanel.add(horizontalSplitPanel);
		
		HorizontalPanel horizontalPanel_1 = new HorizontalPanel();
		verticalPanel.add(horizontalPanel_1);
		
		Label lblStartUrl = new Label("Start Url");
		horizontalPanel_1.add(lblStartUrl);
		
		final TextBox nameField = new TextBox();
		horizontalPanel_1.add(nameField);
		
		// Focus the cursor on the name field when the app loads
		nameField.setFocus(true);
		
		
			
		nameField.selectAll();
		
		final Button startProcessButton = new Button("StartProcess");
		verticalPanel.add(startProcessButton);
		verticalPanel.add(errorLabel);
		final Button sendButton = new Button("Send");
		//ercu closed
		//verticalPanel.add(sendButton);
		
		
		// We can add style names to widgets
		sendButton.addStyleName("sendButton");
		
		Button btnGetRelations = new Button("Get Relations");
		//ercu closed
		//verticalPanel.add(btnGetRelations);
		
		VerticalSplitPanel verticalSplitPanel = new VerticalSplitPanel();
		verticalPanel.add(verticalSplitPanel);
		verticalSplitPanel.setHeight("18px");
		
		//ercu closed
		//HTML htmlNewHtml = new HTML("<b>List of Related People</b>", true);
		//
		
		final HTML htmlNewHtml = new HTML("<b>Log</b>", true);
		verticalPanel.add(htmlNewHtml);
		
		
		htmlNewHtml.setStyleName("scrollable");
		
		final Tree tree = new Tree();
		//ercu closed
		//verticalPanel.add(tree);
		tree.setSize("241px", "180px");
		
		Button btnNewButton = new Button("New button");
		//verticalPanel.add(btnNewButton);
		
		
	
		// Create the popup dialog box
		final DialogBox dialogBox = new DialogBox();
		dialogBox.setText("Remote Procedure Call");
		dialogBox.setAnimationEnabled(true);
		final Button closeButton = new Button("Close");
		// We can set the id of a widget by accessing its Element
		closeButton.getElement().setId("closeButton");
		final Label textToServerLabel = new Label();
		final HTML serverResponseLabel = new HTML();
		VerticalPanel dialogVPanel = new VerticalPanel();
		dialogVPanel.addStyleName("dialogVPanel");
		dialogVPanel.add(new HTML("<b>Sending name to the server:</b>"));
		dialogVPanel.add(textToServerLabel);
		dialogVPanel.add(new HTML("<br><b>Server replies:</b>"));
		dialogVPanel.add(serverResponseLabel);
		dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
		dialogVPanel.add(closeButton);
		dialogBox.setWidget(dialogVPanel);

		// Add a handler to close the DialogBox
		closeButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				dialogBox.hide();
				sendButton.setEnabled(true);
				sendButton.setFocus(true);
			}
		});

		class RelationHandler implements ClickHandler, KeyUpHandler{

			@Override
			public void onKeyUp(KeyUpEvent event) {
				if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
					getRelatedPeople();
				}
				
			}

			private void getRelatedPeople() {
				
				String nameToServer = nameField.getText();
				
				
				entourageService.getRelatedPeople(nameToServer,
						new AsyncCallback<PersonResult[]>() {
							public void onFailure(Throwable caught) {
								// Show the RPC error message to the user
								dialogBox
										.setText("Remote Procedure Call - Failure");
								serverResponseLabel
										.addStyleName("serverResponseLabelError");
								serverResponseLabel.setHTML(SERVER_ERROR);
								dialogBox.center();
								closeButton.setFocus(true);
							}

							public void onSuccess(PersonResult[] result) {
								tree.clear();
								
								for(int i=0; i<result.length; i++){
									PersonResult person = result[i];
									if(person.getParent()== null){
										TreeItem root = new TreeItem(person.getName());
										root.setUserObject(person.getId());
										
										tree.addItem(root);
									}
									else
									{
										int parentId = person.getParent().getId();
										for (int j=0; j<tree.getItemCount(); j++){
											TreeItem currentItem = tree.getItem(j);
											int id = Integer.parseInt(currentItem.getUserObject().toString());
										
											TreeItem itemToBeAdded = new TreeItem(person.getName());
											itemToBeAdded.setUserObject(person.getId());
											
											if(id == parentId)
												currentItem.addItem(itemToBeAdded);
										}
									}
								}
								  
							}
						});
				
			}

			@Override
			public void onClick(ClickEvent event) {
				getRelatedPeople();
				
			}
			
			
		}
		
		
		class LoggingHandler implements ClickHandler, KeyUpHandler{

			@Override
			public void onKeyUp(KeyUpEvent event) {
				if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
					startProcessAndGetLogs();
				}
				
			}

			private void startProcessAndGetLogs() {
				
				final String urlToServer = nameField.getText();
				final String radiusToServer = radiusField.getText();
				
				if (!FieldVerifier.isValidNumber(radiusToServer)) {
					errorLabel.setText("Please enter a valid number.");
					return;
				}
				
				final int radiusNum = Integer.parseInt(radiusToServer);
				startProcessButton.setText("Stop Process");
				
				entourageService.startProcess(radiusNum, urlToServer,
						new AsyncCallback<ProcessResult>() {
							public void onFailure(Throwable caught) {
								// Show the RPC error message to the user
								dialogBox
										.setText("Remote Procedure Call - Failure");
								serverResponseLabel
										.addStyleName("serverResponseLabelError");
								serverResponseLabel.setHTML(SERVER_ERROR);
								dialogBox.center();
								closeButton.setFocus(true);
							}

							@Override
							public void onSuccess(ProcessResult result) {
								 writeLog(result);
								
							}
							
							 

							public void done() { // override
								startProcessButton.setText("Start Process");
							}
							
							public void writeLog(ProcessResult result){
								String html = htmlNewHtml.getHTML();
								htmlNewHtml.setHTML(html+"<br>"+result.getResultStr());
							}
						});
				
			



			
				entourageService.getLogs(1,
					new AsyncCallback<ProcessResult>() {
						public void onFailure(Throwable caught) {
							// Show the RPC error message to the user
							dialogBox
									.setText("Remote Procedure Call - Failure");
							serverResponseLabel
									.addStyleName("serverResponseLabelError");
							serverResponseLabel.setHTML(SERVER_ERROR);
							dialogBox.center();
							closeButton.setFocus(true);
						}

						@Override
						public void onSuccess(ProcessResult result) {
							 if (result.isResult()) {
						            done();
						        } else {
						        	//todo: wait for some (15) seconds
						        	Timer t = new Timer() {
					        	      @Override
					        	      public void run() {
					        	    	  checkAgain();
					        	      }
					        	    };

					        	    t.schedule(60*60 * 1000);

						        }
							 writeLog(result);
							
						}
						
						 private void checkAgain() {
							
							 entourageService.getLogs(1, this);
						}

						public void done() { // override
							startProcessButton.setText("Start Process");
						}
						
						public void writeLog(ProcessResult result){
							String resultStr = result.getResultStr();
							
							if(resultStr == null)
								return;
							
							String html = htmlNewHtml.getHTML();
							htmlNewHtml.setHTML(html+"<br>"+resultStr);
						}
					});
			
		}

			@Override
			public void onClick(ClickEvent event) {
				startProcessAndGetLogs();
				
			}
			
			
		}
		
		

	
		
		
		RelationHandler handlerRel = new RelationHandler();
		btnGetRelations.addClickHandler(handlerRel);
		//nameField.addKeyUpHandler(handlerRel);
		
		LoggingHandler handlerLog = new LoggingHandler();
		
		//connect start process buttons click event to our handler
		startProcessButton.addClickHandler(handlerLog);
		
		//connect name textbox's key up event to our handler
		nameField.addKeyUpHandler(handlerLog);
	}
}
